#pragma once

#include "stdafx.h"
#include "afxext.h"

#include "Node.h"

#include <vector>
using namespace std;

Node::Node(wchar_t* aStr, Node* parentNode){
	this->data.Append(aStr);
	this->parentNode = parentNode;
	this->initBound(&this->textBound);
	this->initBound(&this->bound);
}

Node::~Node(){
	vector<Node*>::iterator iter, end;
	iter = this->childList.begin();
	end = this->childList.end();
 
	for(; iter != end; iter++){
		delete (*iter);
	}
}

void Node::setPos(Pos* aPos){
	this->pos.x = aPos->x;
	this->pos.y = aPos->y;
}

Node* Node::getNextSibling(){
	return this->parentNode->getNextChild(this);
}

Node* Node::getNextChild(Node* child){
	vector<Node*>::iterator before, current, end;
	current = this->childList.begin();
	end = this->childList.end();
	before = current;
	for(;current != end && *current != child; current++){
		before = current;
	}
	if(current == end)
		return this;
	return *before;
}

void Node::addChild(Node* newChild){
	this->childList.push_back(newChild);
}

void Node::setParents(Node* parents){
	this->parentNode = parents;
	return;
}

void Node::draw(IDrawTool* tool){
	// draw self
	this->drawSelf(tool);

	// draw edge

	/* draw child list */

	vector<Node*>::iterator iter, end;
	iter = this->childList.begin();
	end = this->childList.end();

	for(iter = this->childList.begin() ; iter != end ; iter++ )
	{	
		(*iter)->draw(tool);
	}
}

void Node::drawSelf(IDrawTool* tool){
	initBound(&this->textBound);
	
	tool->dc->DrawText( this->data.GetString(), this->data.GetLength(), this->textBound, DT_CALCRECT);

	// draw self
	this->bound.left	= this->pos.x;
	this->bound.top		= this->pos.y - (this->textBound.bottom - this->textBound.top) / 2 - NODE_HEIGHT_MARGINE;
	this->bound.right	= this->pos.x + (this->textBound.right - this->textBound.left ) + NODE_WIDTH_MARGINE;
	this->bound.bottom	= this->pos.y + (this->textBound.bottom - this->textBound.top) / 2 + NODE_HEIGHT_MARGINE;
	
	// draw the border
	tool->dc->RoundRect(this->bound, CPoint(0, 0));

	tool->dc->DrawText(this->data.GetString(), this->data.GetLength(), this->bound, DT_CENTER|DT_VCENTER|DT_SINGLELINE);

	// draw edge
	if( NULL != this->getParents() )
	{
		CRect ParentsBound = this->getParents()->getBound();
		
		tool->dc->MoveTo(ParentsBound.right, ParentsBound.bottom - ParentsBound.Height() / 2 );
		tool->dc->LineTo(bound.left, bound.bottom - bound.Height() / 2 );
	}

	return;
}

vector<Node*> Node::GetChildList()
{
	return this->childList;
}



void Node::appendChar(UINT newChar){
	this->data.AppendChar(newChar);
}

void Node::SetData(CString str)
{
	this->data = str;
}

CRect Node::getBound(){
	return this->bound;
}

CString Node::getData(){
	return this->data;
}

void Node::initBound(CRect* rect){
	rect->top = 0;
	rect->bottom = 0;
	rect->right = 0;
	rect->left = 0;
}

Node* Node::getParents(){
	return this->parentNode;
}

Pos* Node::getPos(){
	return &this->pos;
}

CRect* Node::getTextBound(){
	return &this->textBound;
}

Node* Node::findHitedNode(CPoint point){
	
 	if( this->isHit(point) )
 		return this;

	vector<Node*>::iterator iter, end;
	iter = this->childList.begin();
	end = this->childList.end();
	
	for(; iter!= end; iter++){
		Node* temp;
		if( NULL != (temp = (*iter)->findHitedNode(point)) )
			return temp;
	}

	return NULL;
}

bool Node::isHit(CPoint point){
	
	if( bound.left < point.x && bound.right > point.x && bound.top < point.y && bound.bottom > point.y )
		return true;

	return false;
}